/*
 * # 应用所有存储过程:
 *  Notifying - 通知
 * 
 * # 描述:
 *  向所有用户提供通知功能，包括页面右下角的未读通知、发送新通知、已发送通知列表以及已接收通知列表。
 * 
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */
 
use "pittypat_app";
go

/*
 * # 存储过程 - Sql Server:
 *   Send - 发送新通知
 * 
 * # 描述:
 *   向指定的接收人列表发送一条通知消息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_creating_send"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_creating_send" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_creating_send"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@receivers nvarchar(max), -- 接收人 Id 的列表 
	@urgency tinyint, -- 紧急程度：1-普通，2-紧急，4-特急
	@group nvarchar(30), -- 分组 
	@title nvarchar(50), -- 通知标题 
	@summary nvarchar(200), -- 通知消息摘要 
	@body nvarchar(max), -- 通知正文内容 
	@bodyType tinyint, -- 正文类型代码：1-纯文本，2-HTML
	@funcUrl nvarchar(300), -- 目标功能路径 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@attachmentId uniqueidentifier, -- 附件 Id 
	@notificationCount int out, -- 通知消息数目 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 当前日期时间
	declare @now datetime2 = sysdatetime();

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @notificationCount (通知消息数目)
	set @notificationCount = 0;

	-- 验证参数 @senderId (发送用户的 Id)
	if @senderId is null
	begin
		set @_message = N'没有提供有效的 发送用户的 Id。';
		return;
	end

	-- 验证参数 @receivers (接收人 Id 的列表)
	if @receivers is null or @receivers = ''
	begin
		set @_message = N'没有提供 接收人 Id 的列表。';
		return;
	end
	
	-- 验证参数 @title (通知标题)
	if @title is null or @title = ''
	begin
		set @_message = N'没有提供 通知标题。';
		return;
	end
	
	-- 验证参数 @body (通知正文内容)
	if @body is null or @body = ''
	begin
		set @_message = N'没有提供 通知正文内容。';
		return;
	end

	-- 验证参数 @urgency (紧急程度：1-普通，2-紧急，4-特急)
	if @urgency is null or @urgency not in (1, 2, 4)
	begin
		set @urgency = 1;
	end

	-- 验证参数 @summary (通知消息摘要)
	if @summary is null or @summary = ''
	begin
		set @summary = left(@body, 200);
		return;
	end

	-- 验证参数 @bodyType (正文类型代码：1-纯文本，2-HTML)
	if @bodyType is null or @bodyType < 1 or @bodyType > 2
	begin
		set @bodyType = 1;
	end

	insert into "waln_notifying"."notifications"
	(
		"Id",
		"SenderId",
		"ReceiverId",
		"ReceiveTime",
		"ReadTime",
		"TopTime",
		"Urgency",
		"Group",
		"Title",
		"Summary",
		"Body",
		"BodyType",
		"FuncUrl",
		"RefDataType",
		"RefDataKey",
		"AttachmentId"
	)
	select
		newid(), -- Id 
		@senderId, -- 发送用户的 Id 
		u."Id", -- 接收用户的 Id 
		@now, -- 接收时间
		null, -- 阅读时间 
		(case when @urgency > 1 then @now else null end), -- 置顶时间：紧急或特急总是置顶
		@urgency, -- 紧急程度
		@group, -- 分组
		@title, -- 通知标题
		@summary, -- 通知消息摘要
		@body, -- 通知正文内容 
		@bodyType, -- 正文类型代码
		@funcUrl, -- 目标功能路径
		@refDataType, -- 引用数据的类型 
		@refDataKey, -- 引用数据键值
		@attachmentId  -- 附件 Id 
	from
		"waln_authority"."users" as u
	where
		charindex("waln_notifying"."uuid_to_b64"(u."Id") + ',', @receivers + ',') > 0;

	-- 返回 Send.notificationCount
	set @notificationCount = rowcount_big();

	if @notificationCount is not null and @notificationCount > 0
	begin
		-- 指示操作成功
		set @_success = 1;

		-- 记录操作日志
		set @_log_body = concat(N'向 ', @notificationCount, ' 位用户发送新通知消息。');
		exec "waln_log"."log_op"
			@senderId, -- 当前用户的 Id
			2, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
			'waln_notifying.notifications', -- 相关数据库表的名称列表
			'waln_notifying.p_creating_send', -- 存储过程名称
			@_success, -- 指示操作是否成功
			@_log_body, -- 详细的操作描述
			@_context, -- 当前环境变量参数
			@_log_id out; -- 日志消息的 Id
	end
	else
	begin
		set @_message = N'没有找到接收消息的用户，因此没有发送任何消息。';
	end
end
go

/*
 * # 存储过程 - Sql Server:
 *   Upload - 上传附件
 * 
 * # 描述:
 *   上传一个通知消息的附件文件。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_creating_upload"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_creating_upload" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_creating_upload"
	@userId uniqueidentifier, -- 用户 Id 
	@name nvarchar(100), -- 文件名称 
	@mime nvarchar(100), -- MIME 类型 
	@size bigint, -- 附件文件的大小 
	@url nvarchar(300), -- 文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 附件记录的 Id
	declare @id uniqueidentifier = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @name (文件名称)
	if @name is null or @name = ''
	begin
		set @_message = N'没有提供 文件名称。';
		return;
	end

	-- 验证参数 @size (附件文件的大小)
	if @size is null
	begin
		set @_message = N'没有提供 附件文件的大小。';
		return;
	end

	-- 验证参数 @url (文件路径)
	if @url is null or @url = ''
	begin
		set @_message = N'没有提供 文件路径。';
		return;
	end

	set @id = newid();
	insert into "waln_notifying"."attachments"
	(
		"Id",
		"Name",
		"Mime",
		"Size",
		"Url",
		"UploaderId",
		"UploadTime"
	)
	values
	(
		@id,
		@name,
		@mime,
		@size,
		@url,
		@userId,
		sysdatetime()
	);

	-- 返回 Upload.attachment
	select top(1)
		v.*
	from
		"waln_notifying"."v_creating_attachment" as v 
	where
		v."Id" = @id;

	-- 指示操作成功
	set @_success = 1;

	-- 记录操作日志
	set @_log_body = concat(N'上传了一个通知消息的附件文件：', @url, N'。');
	exec "waln_log"."log_op"
		@userId, -- 当前用户的 Id
		2, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
		'waln_notifying.attachments', -- 相关数据库表的名称列表
		'waln_notifying.p_creating_upload', -- 存储过程名称
		@_success, -- 指示操作是否成功
		@_log_body, -- 详细的操作描述
		@_context, -- 当前环境变量参数
		@_log_id out; -- 日志消息的 Id
end
go

/*
 * # 存储过程 - Sql Server:
 *   DeleteAttachment - 删除附件
 * 
 * # 描述:
 *   删除通知中包含的附件文件。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_creating_deleteattachment"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_creating_deleteattachment" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_creating_deleteattachment"
	@uploaderId uniqueidentifier, -- 上传人的 Id 
	@id uniqueidentifier, -- Id 
	@url nvarchar(300) out, -- 文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @url (文件路径)
	set @url = null;

	-- 验证参数 @uploaderId (上传人的 Id)
	if @uploaderId is null
	begin
		set @_message = N'没有提供有效的 上传人的 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	-- 查询附件文件的路径，以便中间层能够删除对应的文件
	select @url = "Url" from "waln_notifying"."attachments" where "Id" = @id and "UploaderId" = @uploaderId;
	if @url is null
	begin
		set @_success = 1;
		return;
	end

	delete from 
		"waln_notifying"."attachments" 
	where 
		"Id" = @id; 

	-- 指示操作成功
	set @_success = 1;

	-- 记录操作日志
	set @_log_body = concat(N'删除了一个通知消息的附件文件：', @url, N'。');
	exec "waln_log"."log_op"
		@uploaderId, -- 当前用户的 Id
		8, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
		'waln_notifying.attachments', -- 相关数据库表的名称列表
		'waln_notifying.p_creating_deleteattachment', -- 存储过程名称
		@_success, -- 指示操作是否成功
		@_log_body, -- 详细的操作描述
		@_context, -- 当前环境变量参数
		@_log_id out; -- 日志消息的 Id
end
go

/*
 * # 存储过程 - Sql Server:
 *   Receivers - 接收人列表
 * 
 * # 描述:
 *   查询当前用户的可用所有接收人的列表。用于在发送通知消息时选择接收人。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_creating_receivers"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_creating_receivers" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_creating_receivers"
	@pageIndex bigint, -- 页码
	@pageSize bigint, -- 页面尺寸
	@totalRows bigint out, -- 总行数
	@orderName nvarchar(50), -- 排序名称
	@orderDirection nvarchar(4), -- 排序方向
	@userId uniqueidentifier, -- 用户 Id
	@name nvarchar(30), -- 接收人名称
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功
	@_message nvarchar(4000) out  -- 操作中产生的消息
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end
	
    -- 初始化 out 参数
    set @totalRows = 0; -- 总行数

    -- 验证参数 @pageIndex (页码)
    if @pageIndex is null or @pageIndex < 1 
	begin
        -- 默认分页查询的页码，从 1 开始
        set @pageIndex = 1;
    end

    -- 验证参数 @pageSize (页面尺寸)
    if @pageSize is null or @pageSize < 1 
	begin
        -- 默认分页查询的页面尺寸
        set @pageSize = 20;
    end

    -- 验证参数 @orderName (排序名称)
    if @orderName is null or @orderName = '' or @orderName not in 
    (
        -- 确保排序名称是以下名称之一，防止 SQL 注入式攻击
        'Name'
    ) 
	begin
        -- 默认排序列的标识符
        set @orderName = 'Name';
    end

    -- 验证参数 @orderDirection (排序方向)
    if @orderDirection is null or @orderDirection not in ('asc', 'desc') 
	begin
        -- 默认排序方向
        set @orderDirection = 'asc';
    end
	
	-- 为 like 运算转义字符串参数 @keyword
	set @name = "waln_authority"."like_escape"(@name);

    -- 参数 @totalRows (总行数)
	select 
		@totalRows = count_big(*) 
	from 
		"waln_authority"."users" as v 
	where 
		(@name is null) or (v."LoginName" like @name) or (v."Name" like @name); 

	-- 没有满足条件的记录行
	if @totalRows is null or @totalRows < 1
	begin
		set @totalRows = 0;
		-- 指示操作成功
		set @_success = 1;
		return;
	end

	-- 动态查询命令文本
	declare @_page_sql nvarchar(4000);
	-- 动态查询命令参数定义文本
	declare @_params_def nvarchar(4000);
	-- 分页用的起始行号，从 1 开始
	declare @_start_row bigint;
	-- 分页用的截至行号，从 1 开始
	declare @_end_row bigint;

	-- 根据页码和页面尺寸计算起始行号
	set @_start_row = 1;
	if @pageIndex > 1
	begin
		set @_start_row = (@pageIndex - 1) * @pageSize + 1;
	end

	-- 根据页面尺寸和起始行号计算截至行号
	set @_end_row = @_start_row + @pageSize - 1

	-- 动态创建查询命令文本
	set @_page_sql = 
		'select ' + 
			'__pv.* ' + 
		'from ' + 
		'(' + 
			'select ' + 
				'v."Id",concat(v."Name", '' ('', v."LoginName", '')'') as "Name",v."FaceUrl", ' + 
				'(row_number() over(order by ' + @orderName + ' ' + @orderDirection + ')) as __row_no ' + 
			'from ' + 
			'"waln_authority"."users" as v '+ 
			'where ' + 
				'(@name is null) or (v."LoginName" like @name) or (v."Name" like @name) ' + 
		') as __pv ' + 
		'where ' + 
			'__row_no >= ' + cast(@_start_row as varchar(20)) + ' and __row_no <= ' + cast(@_end_row as varchar(20));

	set @_params_def = 
		'@name nvarchar(50)'; 

	exec "dbo"."sp_executesql" @_page_sql, @_params_def, 
		@name;

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Count - 未读通知数目
 * 
 * # 描述:
 *   查询当前用户已经接收到的，尚未读取的通知的总数。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_unread_count"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_unread_count" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_unread_count"
	@receiverId uniqueidentifier, -- 接收用户的 Id 
	@total bigint out, -- 通知数目 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @total (通知数目)
	set @total = null;

	-- 验证参数 @receiverId (接收用户的 Id)
	if @receiverId is null
	begin
		set @_message = N'没有提供有效的 接收用户的 Id。';
		return;
	end

	-- 返回 Count.total
    select 
		@total = count_big("PK") 
    from 
		"waln_notifying"."notifications"
    where 
		"ReceiverId" = @receiverId and
        "ReadTime" is null;

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   List - 新通知列表
 * 
 * # 描述:
 *   查询当前用户已经接收到的新通知的列表。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_unread_list"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_unread_list" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_unread_list"
	@userId uniqueidentifier, -- 用户 Id 
	@total bigint out, -- 通知总数 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @total (通知总数)
	set @total = 0;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 参数 @total (通知总数)
	select 
		@total = count_big("Id") 
	from 
		"waln_notifying"."v_unread_notification" as v 
	where 
		v."ReceiverId" = @userId and
        v."ReadTime" is null; 

	-- 没有满足条件的记录行
	if @total is null or @total < 1
	begin
		set @total = 0;
		return;
	end
	
	-- 返回 List.notifications
	select 
		v.*
    from 
		"waln_notifying"."v_unread_notification" as v
    where 
		v."ReceiverId" = @userId and
        v."ReadTime" is null;

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Read - 标记为已读
 * 
 * # 描述:
 *   将指定的通知标记为已经阅读。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_unread_read"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_unread_read" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_unread_read"
	@userId uniqueidentifier, -- 用户 Id 
	@id uniqueidentifier, -- Id 
	@readTime datetime2 out, -- 阅读时间 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;
	
	-- 当前日期时间
	declare @now datetime2 = sysdatetime();

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @readTime (阅读时间)
	set @readTime = null;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	update 
		"waln_notifying"."notifications" 
	set 
		"ReadTime" = @now
	where 
		"Id" = @id and "ReceiverId" = @userId; 

	if @@rowcount > 0
	begin
		set @readTime = @now;
	end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   List - 通知列表
 * 
 * # 描述:
 *   查询当前用户接收到的通知列表。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_inbox_list"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_inbox_list" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_inbox_list"
	@pageIndex bigint, -- 页码 
	@pageSize bigint, -- 页面尺寸 
	@totalRows bigint out, -- 总行数 
	@orderName nvarchar(30), -- 排序名称 
	@orderDirection nvarchar(4), -- 排序方向 
	@userId uniqueidentifier, -- 用户 Id 
	@title nvarchar(50), -- 通知标题 
	@senderName nvarchar(50), -- 发送人名称 
	@isRead bit, -- 是否已读 
	@urgency tinyint, -- 紧急程度 
	@group nvarchar(30), -- 分组 
	@receiveTimeFrom datetime2, -- 起始接收时间 
	@receiveTimeTo datetime2, -- 截至接收时间 
	@includesTop bit, -- 是否包含置顶通知 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @totalRows (总行数)
	set @totalRows = 0;

	-- 验证参数 @pageIndex (页码)
	if @pageIndex is null or @pageIndex < 1
	begin
		-- 默认分页查询的页码，从 1 开始
		set @pageIndex = 1;
	end

	-- 验证参数 @pageSize (页面尺寸)
	if @pageSize is null or @pageSize < 1
	begin
		-- 默认分页查询的页面尺寸
		set @pageSize = 20;
	end

	-- 验证参数 @orderName (排序名称)
	if @orderName is null or @orderName = '' or @orderName not in 
	(
		-- 确保排序名称是以下名称之一，防止 SQL 注入式攻击
		'Title', 
		'Urgency', 
		'Group', 
		'ReceiveTime'
	)
	begin
		-- 默认排序列
		set @orderName = 'ReceiveTime';
	end

	-- 验证参数 @orderDirection (排序方向)
	if @orderDirection is null or @orderDirection not in ('asc', 'desc')
	begin
		-- 默认排序方向
		set @orderDirection = 'desc';
	end

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 返回 List.notifications
	-- 为 like 运算转义字符串参数 @title
	set @title = "waln_notifying"."like_escape"(@title);
	-- 为 like 运算转义字符串参数 @senderName
	set @senderName = "waln_notifying"."like_escape"(@senderName);
	-- 为 like 运算转义字符串参数 @group
	set @group = "waln_notifying"."like_escape"(@group);
	-- 截止时间
	set @receiveTimeTo = case when @receiveTimeTo is null then null else dateadd("DAY", 1, @receiveTimeTo) end;

	-- 参数 @totalRows (总行数)
	select 
		@totalRows = count_big(*) 
	from 
		"waln_notifying"."v_inbox_notification" as v 
	where 
		(v."ReceiverId" = @userId) and (v."TopTime" is null) and 
		((@title is null) or (v."Title" like @title)) and 
		((@senderName is null) or (v."senderName" like @senderName)) and 
		((@isRead is null) or (@isRead = 1 and v."ReadTime" is not null) or (@isRead = 0 and v."ReadTime" is null)) and 
		((@urgency is null) or ((v."Urgency" & @urgency) <> 0)) and 
		((@group is null) or (v."Group" like @group)) and 
		((@receiveTimeFrom is null) or (v."ReceiveTime" >= @receiveTimeFrom)) and 
		((@receiveTimeTo is null) or (v."ReceiveTime" < @receiveTimeTo)); 

	-- 没有满足条件的记录行
	if @totalRows is null or @totalRows < 1
	begin
		set @totalRows = 0;

		-- 置顶清单
		if @includesTop is not null and @includesTop = 1
		begin
			-- 确保第一个结果集合为非置顶的清单
			select * from "waln_notifying"."v_inbox_notification" as v where 1=2;

			-- 已经置顶的通知清单
			select 
				v.*
			from 
				"waln_notifying"."v_inbox_notification" as v
			where
				v."ReceiverId" = @userId and
				v."TopTime" is not null;
		end

		-- 指示操作成功
		set @_success = 1;
		return;
	end

	-- 动态查询命令文本
	declare @_page_sql nvarchar(4000);
	-- 动态查询命令参数定义文本
	declare @_params_def nvarchar(4000);
	-- 分页用的起始行号，从 1 开始
	declare @_start_row bigint;
	-- 分页用的截至行号，从 1 开始
	declare @_end_row bigint;

	-- 根据页码和页面尺寸计算起始行号
	set @_start_row = 1;
	if @pageIndex > 1
	begin
		set @_start_row = (@pageIndex - 1) * @pageSize + 1;
	end

	-- 根据页面尺寸和起始行号计算截至行号
	set @_end_row = @_start_row + @pageSize - 1

	-- 动态创建查询命令文本
	set @_page_sql = 
		'select ' + 
			'__pv.* ' + 
		'from ' + 
		'(' + 
			'select ' + 
				'v.*, ' + 
				'(row_number() over(order by ' + @orderName + ' ' + @orderDirection + ')) as __row_no ' + 
			'from ' + 
			'"waln_notifying"."v_inbox_notification" as v '+ 
			'where ' + 
				'(v."ReceiverId" = @userId) and (v."TopTime" is null) and ' + 
				'((@title is null) or (v."Title" like @title)) and ' + 
				'((@senderName is null) or (v."senderName" like @senderName)) and ' + 
				'((@isRead is null) or (@isRead = 1 and v."ReadTime" is not null) or (@isRead = 0 and v."ReadTime" is null)) and ' + 
				'((@urgency is null) or ((v."Urgency" & @urgency) <> 0)) and ' + 
				'((@group is null) or (v."Group" like @group)) and ' + 
				'((@receiveTimeFrom is null) or (v."ReceiveTime" >= @receiveTimeFrom)) and ' + 
				'((@receiveTimeTo is null) or (v."ReceiveTime" < @receiveTimeTo)) ' + 
		') as __pv ' + 
		'where ' + 
			'__row_no >= ' + cast(@_start_row as varchar(20)) + ' and __row_no <= ' + cast(@_end_row as varchar(20));

	set @_params_def = 
		'@userId uniqueidentifier,' + 
		'@title nvarchar(50),' + 
		'@senderName nvarchar(50),' + 
		'@isRead bit,' + 
		'@urgency tinyint,' + 
		'@group nvarchar(30),' + 
		'@receiveTimeFrom datetime2,' + 
		'@receiveTimeTo datetime2'; 

	exec "dbo"."sp_executesql" @_page_sql, @_params_def, 
		@userId,
		@title, 
		@senderName, 
		@isRead, 
		@urgency, 
		@group, 
		@receiveTimeFrom, 
		@receiveTimeTo;

	if @includesTop is not null and @includesTop = 1 
	begin
        select 
			v.*
        from 
			"waln_notifying"."v_inbox_notification" as v
		where
			v."ReceiverId" = @userId and
            v."TopTime" is not null;
	end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Details - 详细信息
 * 
 * # 描述:
 *   查询和显示通知的详细信息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_inbox_details"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_inbox_details" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_inbox_details"
	@userId uniqueidentifier, -- 用户 Id 
	@id uniqueidentifier, -- Id 
	@body nvarchar(max) out, -- 通知正文内容 
	@readTime datetime2 out, -- 阅读时间 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 消息主键
	declare @pk bigint = null;
	-- 附件的 Id
	declare @attachmentId uniqueidentifier = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @body (通知正文内容)
	set @body = null;

	-- 初始化 out 参数 @readTime (阅读时间)
	set @readTime = null;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	-- 返回 Details.body
    select 
		@pk = "PK", @body = "Body", @attachmentId = "AttachmentId", @readTime = "ReadTime"
	from 
		"waln_notifying"."notifications"
	where
		"Id" = @id and 
        "ReceiverId" = @userId;
        
	if @pk is null
	begin
        set @_message = N'没有找到通知消息。';
        return;
    end
    
    -- 将消息标记为已读
    if @readTime is null
	begin
		set @readTime = sysdatetime();
		update "waln_notifying"."notifications" set "ReadTime" = @readTime where "PK" = @pk;
    end

    -- 返回 Details.attachment
    if @attachmentId is not null
	begin
		select 
			v.* 
		from 
			"waln_notifying"."v_inbox_attachment" as v 
		where 
			v."Id" = @attachmentId;
	end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Read - 标记为已读
 * 
 * # 描述:
 *   将指定的通知标记为已经阅读。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_inbox_read"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_inbox_read" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_inbox_read"
	@userId uniqueidentifier, -- 用户 Id 
	@id uniqueidentifier, -- Id 
	@isRead bit, -- 是否已读 
	@readTime datetime2 out, -- 阅读时间 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 当前日期时间
	declare @now datetime2 = sysdatetime();

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @readTime (阅读时间)
	set @readTime = null;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	-- 将通知消息的阅读时间设置为当前时间
    update 
        "waln_notifying"."notifications" 
    set 
        "ReadTime" = case when @isRead is not null and @isRead = 1 then @now else null end
    where 
        "Id" = @id and "ReceiverId" = @userId; 

    -- 返回 Read.readTime
    if rowcount_big() > 0 
	begin
		set @readTime = @now;
    end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Top - 置顶
 * 
 * # 描述:
 *   将指定的通知置顶。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_inbox_top"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_inbox_top" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_inbox_top"
	@userId uniqueidentifier, -- 用户 Id 
	@id uniqueidentifier, -- Id 
	@isTop bit, -- 是否置顶 
	@topTime datetime2 out, -- 置顶时间 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 当前日期时间
	declare @now datetime2 = sysdatetime();

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @topTime (置顶时间)
	set @topTime = null;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	-- 将通知消息的置顶时间设置为当前时间
	update 
		"waln_notifying"."notifications" 
	set 
		"TopTime" = case when @isTop is not null and @isTop = 1 then @now else null end
	where 
		"Id" = @id and "ReceiverId" = @userId; 

    -- 返回 Read.topTime
    if rowcount_big() > 0
	begin
		set @topTime = @now;
    end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Delete - 删除通知
 * 
 * # 描述:
 *   删除一条或者多条通知消息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_inbox_delete"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_inbox_delete" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_inbox_delete"
	@receiverId uniqueidentifier, -- 接收用户的 Id 
	@ids nvarchar(4000), -- 通知 Id 的列表 
	@attachmentUrls nvarchar(max) out, -- 附件文件路径列表 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 消息主键
	declare @pk bigint = null;
	-- 附件的 Id
	declare @attachmentId uniqueidentifier = null;
	-- 删除计数
	declare @deletedCount bigint = 0;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @attachmentUrls (附件文件路径列表)
	set @attachmentUrls = null;

	-- 验证参数 @receiverId (接收用户的 Id)
	if @receiverId is null
	begin
		set @_message = N'没有提供有效的 接收用户的 Id。';
		return;
	end

	-- 验证参数 @ids (通知 Id 的列表)
	if @ids is null or @ids = ''
	begin
		set @_message = N'没有提供 通知 Id 的列表。';
		return;
	end
    
    -- 尚未阅读的消息不能被删除
    
    select 
		@pk = "PK", @attachmentId = "AttachmentId"
    from 
		"waln_notifying"."notifications"
	where 
		"ReceiverId" = @receiverId and 
		"Id" = "waln_notifying"."b64_to_uuid"(@ids); -- 目前仅支持单条消息删除 
        
	if @pk is null
	begin
		set @_success = 1;
		return;
    end
    
    -- 如果通知存在附件，并且附件没有被其他通知使用，则返回附件的路径，以便删除物理文件
    if @attachmentId is not null and not exists (select "PK" from "waln_notifying"."notifications" where "AttachmentId" = @attachmentId and "PK" <> @pk)
	begin
		select @attachmentUrls = "Url"
		from "attachments"
		where "Id" = @attachmentId;
        
        -- 删除附件
        delete from "waln_notifying"."attachments" where "Id" = @attachmentId;
    end
	
	delete from 
		"waln_notifying"."notifications" 
	where 
		"PK" = @pk; 
        
    set @deletedCount = rowcount_big();

    -- 指示操作成功
    set @_success = 1;

	if @deletedCount > 0 
	begin
		-- 记录操作日志
		set @_log_body = concat(N'删除了 ', @deletedCount, N' 条已经接收到的通知消息。');
		exec "waln_log"."log_op"
			@receiverId, -- 当前用户的 Id
			8, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
			'waln_notifying.notifications', -- 相关数据库表的名称列表
			'waln_notifying.p_inbox_delete', -- 存储过程名称
			@_success, -- 指示操作是否成功
			@_log_body, -- 详细的操作描述
			@_context, -- 当前环境变量参数
			@_log_id out; -- 日志消息的 Id
    end
end
go

/*
 * # 存储过程 - Sql Server:
 *   List - 通知列表
 * 
 * # 描述:
 *   查询当前用户接收到的通知列表。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_list"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_list" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_list"
	@pageIndex bigint, -- 页码 
	@pageSize bigint, -- 页面尺寸 
	@totalRows bigint out, -- 总行数 
	@orderName nvarchar(30), -- 排序名称 
	@orderDirection nvarchar(4), -- 排序方向 
	@userId uniqueidentifier, -- 用户 Id 
	@title nvarchar(50), -- 通知标题 
	@receiverName nvarchar(50), -- 接收人名称 
	@isRead bit, -- 是否已读 
	@urgency tinyint, -- 紧急程度 
	@group nvarchar(30), -- 分组 
	@sendTimeFrom datetime2, -- 起始发送日期 
	@sendTimeTo datetime2, -- 截至发送日期 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @totalRows (总行数)
	set @totalRows = 0;

	-- 验证参数 @pageIndex (页码)
	if @pageIndex is null or @pageIndex < 1
	begin
		-- 默认分页查询的页码，从 1 开始
		set @pageIndex = 1;
	end

	-- 验证参数 @pageSize (页面尺寸)
	if @pageSize is null or @pageSize < 1
	begin
		-- 默认分页查询的页面尺寸
		set @pageSize = 20;
	end

	-- 验证参数 @orderName (排序名称)
	if @orderName is null or @orderName = '' or @orderName not in 
	(
		-- 确保排序名称是以下名称之一，防止 SQL 注入式攻击
		'Title', 
		'Urgency', 
		'Group', 
		'ReceiveTime'
	)
	begin
		-- 默认排序列
		set @orderName = 'ReceiveTime';
	end

	-- 验证参数 @orderDirection (排序方向)
	if @orderDirection is null or @orderDirection not in ('asc', 'desc')
	begin
		-- 默认排序方向
		set @orderDirection = 'desc';
	end

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 返回 List.notifications
	-- 为 like 运算转义字符串参数 @title
	set @title = "waln_notifying"."like_escape"(@title);
	-- 为 like 运算转义字符串参数 @receiverName
	set @receiverName = "waln_notifying"."like_escape"(@receiverName);
	-- 为 like 运算转义字符串参数 @group
	set @group = "waln_notifying"."like_escape"(@group);
	-- 截至时间
	set @sendTimeTo = case when @sendTimeTo is null then null else dateadd("DAY", 1, @sendTimeTo) end;

	-- 参数 @totalRows (总行数)
	select 
		@totalRows = count_big(*) 
	from 
		"waln_notifying"."v_outbox_notification" as v 
	where 
		(v."SenderId" = @userId) and 
		((@title is null) or (v."Title" like @title)) and 
		((@receiverName is null) or (v."ReceiverName" like @receiverName)) and 
		((@isRead is null) or (@isRead = 1 and v."ReadTime" is not null) or (@isRead = 0 and v."ReadTime" is null)) and 
		((@urgency is null) or ((v."Urgency" & @urgency) <> 0)) and 
		((@group is null) or (v."Group" like @group)) and 
		((@sendTimeFrom is null) or (v."ReceiveTime" >= @sendTimeFrom)) and 
		((@sendTimeTo is null) or (v."ReceiveTime" < @sendTimeTo)); 

	-- 没有满足条件的记录行
	if @totalRows is null or @totalRows < 1
	begin
		set @totalRows = 0;
		-- 指示操作成功
		set @_success = 1;
		return;
	end

	-- 动态查询命令文本
	declare @_page_sql nvarchar(4000);
	-- 动态查询命令参数定义文本
	declare @_params_def nvarchar(4000);
	-- 分页用的起始行号，从 1 开始
	declare @_start_row bigint;
	-- 分页用的截至行号，从 1 开始
	declare @_end_row bigint;

	-- 根据页码和页面尺寸计算起始行号
	set @_start_row = 1;
	if @pageIndex > 1
	begin
		set @_start_row = (@pageIndex - 1) * @pageSize + 1;
	end

	-- 根据页面尺寸和起始行号计算截至行号
	set @_end_row = @_start_row + @pageSize - 1

	-- 动态创建查询命令文本
	set @_page_sql = 
		'select ' + 
			'__pv.* ' + 
		'from ' + 
		'(' + 
			'select ' + 
				'v.*, ' + 
				'(row_number() over(order by ' + @orderName + ' ' + @orderDirection + ')) as __row_no ' + 
			'from ' + 
			'"waln_notifying"."v_outbox_notification" as v '+ 
			'where ' + 
				'(v."SenderId" = @userId) and ' + 
				'((@title is null) or (v."Title" like @title)) and ' + 
				'((@receiverName is null) or (v."ReceiverName" like @receiverName)) and ' + 
				'((@isRead is null) or (@isRead = 1 and v."ReadTime" is not null) or (@isRead = 0 and v."ReadTime" is null)) and ' + 
				'((@urgency is null) or ((v."Urgency" & @urgency) <> 0)) and ' + 
				'((@group is null) or (v."Group" like @group)) and ' + 
				'((@sendTimeFrom is null) or (v."ReceiveTime" >= @sendTimeFrom)) and ' + 
				'((@sendTimeTo is null) or (v."ReceiveTime" < @sendTimeTo)) ' + 
		') as __pv ' + 
		'where ' + 
			'__row_no >= ' + cast(@_start_row as varchar(20)) + ' and __row_no <= ' + cast(@_end_row as varchar(20));

	set @_params_def = 
		'@userId uniqueidentifier,' + 
		'@title nvarchar(50),' + 
		'@receiverName nvarchar(50),' + 
		'@isRead bit,' + 
		'@urgency tinyint,' + 
		'@group nvarchar(30),' + 
		'@sendTimeFrom datetime2,' + 
		'@sendTimeTo datetime2'; 

	exec "dbo"."sp_executesql" @_page_sql, @_params_def, 
		@userId,
		@title, 
		@receiverName, 
		@isRead, 
		@urgency, 
		@group, 
		@sendTimeFrom, 
		@sendTimeTo;

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Details - 详细信息
 * 
 * # 描述:
 *   查询和显示通知的详细信息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_details"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_details" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_details"
	@userId uniqueidentifier, -- 用户 Id 
	@id uniqueidentifier, -- Id 
	@body nvarchar(max) out, -- 通知正文内容 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- Id
	declare @attachmentId uniqueidentifier = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @body (通知正文内容)
	set @body = null;

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end

	-- 返回 Details.body
    select 
		@body = "Body", @attachmentId = "AttachmentId"
	from 
		"waln_notifying"."notifications"
	where
		"Id" = @id and 
        "SenderId" = @userId;

    -- 返回 Details.attachment
    if @attachmentId is not null
	begin
		select 
			v.* 
		from 
			"waln_notifying"."v_outbox_attachment" as v 
		where 
			v."Id" = @attachmentId;
	end

	-- 指示操作成功
	set @_success = 1;
end
go

/*
 * # 存储过程 - Sql Server:
 *   Delete - 删除通知
 * 
 * # 描述:
 *   删除一条或者多条通知消息。已经阅读的消息不能被删除。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_delete"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_delete" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_delete"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@ids nvarchar(4000), -- 通知 Id 的列表 
	@attachmentUrls nvarchar(max) out, -- 附件路径列表 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 消息主键
	declare @pk bigint = null;
	-- 附件的 Id
	declare @attachmentId uniqueidentifier = null;
	-- 删除记录计数
	declare @deletedCount bigint = 0;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @attachmentUrls (附件路径列表)
	set @attachmentUrls = null;

	-- 验证参数 @senderId (发送用户的 Id)
	if @senderId is null
	begin
		set @_message = N'没有提供有效的 发送用户的 Id。';
		return;
	end

	-- 验证参数 @ids (通知 Id 的列表)
	if @ids is null or @ids = ''
	begin
		set @_message = N'没有提供 通知 Id 的列表。';
		return;
	end
    
    -- 已经阅读的消息不能被删除
    
    select 
		@pk = "PK", @attachmentId = "AttachmentId"
    from 
		"waln_notifying"."notifications"
	where 
		"SenderId" = @senderId and 
		"ReadTime" is null and -- 已经阅读的消息不能被删除
		"Id" = "waln_notifying"."b64_to_uuid"(@ids); -- 目前仅支持单条消息删除
        
	if @pk is null 
	begin
		set @_success = 1;
		return;
    end
    
    -- 如果通知存在附件，并且附件没有被其他通知使用，则返回附件的路径，以便删除物理文件
    if @attachmentId is not null and not exists (select "PK" from "waln_notifying"."notifications" where "AttachmentId" = @attachmentId and "PK" <> @pk) 
	begin
		select @attachmentUrls = "Url"
		from "waln_notifying"."attachments"
		where "Id" = @attachmentId;
        
        -- 删除附件
        delete from "waln_notifying"."attachments" where "Id" = @attachmentId;
    end
	
	delete from 
		"waln_notifying"."notifications" 
	where 
		"PK" = @pk; 
    
    set @deletedCount = rowcount_big();

    -- 指示操作成功
    set @_success = 1;

	if @deletedCount > 0 
	begin
		-- 记录操作日志
		set @_log_body = concat(N'删除了 ', @deletedCount, N' 条已经发送出去的通知消息。');
		exec "waln_log"."log_op"
			@senderId, -- 当前用户的 Id
			8, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
			'waln_notifying.notifications', -- 相关数据库表的名称列表
			'waln_notifying.p_outbox_delete', -- 存储过程名称
			@_success, -- 指示操作是否成功
			@_log_body, -- 详细的操作描述
			@_context, -- 当前环境变量参数
			@_log_id out; -- 日志消息的 Id
    end
end
go

/*
 * # 存储过程 - Sql Server:
 *   Edit - 修改通知
 * 
 * # 描述:
 *   修改一条已经发送的通知消息，可以修改的属性包括：标题、摘要、紧急程度、分组和正文，附件也可以在删除后重新上传。已经阅读的消息不能被修改。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_edit"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_edit" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_edit"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@id uniqueidentifier, -- Id 
	@urgency tinyint, -- 紧急程度 
	@group nvarchar(30), -- 分组 
	@title nvarchar(50), -- 通知标题 
	@summary nvarchar(200), -- 通知消息摘要 
	@body nvarchar(max), -- 通知正文内容 
	@bodyType tinyint, -- 正文类型代码 
	@funcUrl nvarchar(300), -- 目标功能路径 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@attachmentId uniqueidentifier, -- 附件 Id 
	@oldAttachmentUrl nvarchar(300) out, -- 原始附件文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 消息主键
	declare @pk bigint = null;
	-- 原始附件的 Id
	declare @oldAttachmentId uniqueidentifier = null;
	-- 消息阅读时间
	declare @readTime datetime2 = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @oldAttachmentUrl (原始附件文件路径)
	set @oldAttachmentUrl = null;

	-- 验证参数 @senderId (发送用户的 Id)
	if @senderId is null
	begin
		set @_message = N'没有提供有效的 发送用户的 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end
    
    select @pk = "PK", @readTime = "ReadTime", @oldAttachmentId = "AttachmentId"
    from "waln_notifying"."notifications" 
    where "Id" = @id and "SenderId" = @senderId;
    
    if @pk is null 
	begin
        set @_message = N'没有找到要修改的通知消息记录。';
        return;
    end
    
    if @readTime is not null 
	begin
        set @_message = N'已经被接收人标记为已读的消息不能修改。';
        return;
    end
    
    -- 如果原来的附件不再有用，则删除该附件
    if  @oldAttachmentId is not null and 
		((@attachmentId is null) or (@attachmentId is not null and @oldAttachmentId <> @attachmentId)) and
        not exists (select * from "waln_notifying"."Notifications" where "AttachmentId" = @oldAttachmentId and "PK" <> @pk)
	begin
		select @oldAttachmentUrl = "Url"
        from "waln_notifying"."attachments"
        where "Id" = @oldAttachmentId;
        
        delete from "waln_notifying"."attachments" where "Id" = @oldAttachmentId;
    end

    update 
        "waln_notifying"."notifications" 
    set 
        "Urgency" = case when @urgency is null or @urgency not in (1, 2, 4) then "Urgency" else @urgency end, 
        "Group" = case when @group is null or @group = '' then "Group" else @group end, 
        "Title" = case when @title is null or @title = '' then "Title" else @title end, 
        "Summary" = case when @summary is null or @summary = '' then (case when @body is null or @body = '' then "Summary" else left(@body, 200) end) else @summary end, 
        "Body" = case when @body is null or @body = '' then "Body" else @body end, 
        "BodyType" = case when @bodyType is null or @bodyType not in (1, 2) then "BodyType" else @bodyType end, 
        "FuncUrl" = case when @funcUrl is null or @funcUrl = '' then "FuncUrl" else @funcUrl end, 
        "RefDataType" = case when @refDataType is null or @refDataType = '' then "RefDataType" else @refDataType end, 
        "RefDataKey" = case when @refDataKey is null or @refDataKey = '' then "RefDataKey" else @refDataKey end, 
        "AttachmentId" = @attachmentId
    where 
        "PK" = @pk; 

    -- 返回 Edit.notification
    select 
        v.* 
    from 
        "waln_notifying"."v_outbox_notification" as v 
    where 
        v."PK" = @pk; 

    -- 指示操作成功
    set @_success = 1;

    -- 记录操作日志
	set @_log_body = concat(N'修改了一条已经发送的通知消息。通知消息的 Id 为：', @id, N'。');
	exec "waln_log"."log_op"
        @senderId, -- 当前用户的 Id
        4, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
        'waln_notifying.notifications', -- 相关数据库表的名称列表
        'waln_notifying.p_outbox_edit', -- 存储过程名称
		@_success, -- 指示操作是否成功
		@_log_body, -- 详细的操作描述
		@_context, -- 当前环境变量参数
		@_log_id out; -- 日志消息的 Id
end
go

/*
 * # 存储过程 - Sql Server:
 *   Upload - 上传附件
 * 
 * # 描述:
 *   上传一个通知消息的附件文件。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_upload"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_upload" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_upload"
	@userId uniqueidentifier, -- 用户 Id 
	@name nvarchar(100), -- 文件名称 
	@mime nvarchar(100), -- MIME 类型 
	@size bigint, -- 附件文件的大小 
	@url nvarchar(300), -- 文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 附件的 Id
	declare @id uniqueidentifier = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 验证参数 @userId (用户 Id)
	if @userId is null
	begin
		set @_message = N'没有提供有效的 用户 Id。';
		return;
	end

	-- 验证参数 @name (文件名称)
	if @name is null or @name = ''
	begin
		set @_message = N'没有提供 文件名称。';
		return;
	end

	-- 验证参数 @size (附件文件的大小)
	if @size is null
	begin
		set @_message = N'没有提供 附件文件的大小。';
		return;
	end

	-- 验证参数 @url (文件路径)
	if @url is null or @url = ''
	begin
		set @_message = N'没有提供 文件路径。';
		return;
	end

	set @id = newid();
	insert into "waln_notifying"."attachments"
	(
		"Id",
        "Name", 
        "Mime", 
        "Size", 
        "Url",
        "UploaderId",
        "UploadTime"
	)
	values
	(
		@id,
		@name,
		@mime,
		@size,
		@url,
		@userId,
		sysdatetime()
	);

	-- 返回 Upload.attachment
	select top(1)
		v.*
	from
		"waln_notifying"."v_outbox_attachment" as v 
	where
		v."Id" = @id;

	-- 指示操作成功
	set @_success = 1;

	-- 记录操作日志
	set @_log_body = concat(N'上传了一个通知消息的附件文件：', @url, N'。');
	exec "waln_log"."log_op"
		@userId, -- 当前用户的 Id
		2, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
		'waln_notifying.attachments', -- 相关数据库表的名称列表
		'waln_notifying.p_outbox_upload', -- 存储过程名称
		@_success, -- 指示操作是否成功
		@_log_body, -- 详细的操作描述
		@_context, -- 当前环境变量参数
		@_log_id out; -- 日志消息的 Id
end
go

/*
 * # 存储过程 - Sql Server:
 *   DeleteAttachment - 删除附件
 * 
 * # 描述:
 *   删除通知中包含的附件文件。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_outbox_deleteattachment"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_outbox_deleteattachment" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_outbox_deleteattachment"
	@uploaderId uniqueidentifier, -- 上传人的 Id 
	@id uniqueidentifier, -- Id 
	@url nvarchar(300) out, -- 文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 初始化 out 参数 @url (文件路径)
	set @url = null;

	-- 验证参数 @uploaderId (上传人的 Id)
	if @uploaderId is null
	begin
		set @_message = N'没有提供有效的 上传人的 Id。';
		return;
	end

	-- 验证参数 @id (Id)
	if @id is null
	begin
		set @_message = N'没有提供 Id。';
		return;
	end
    
    select @url = "Url" from "waln_notifying"."attachments" where "Id" = @id and "UploaderId" = @uploaderId;
    if @url is null 
	begin
		-- 没有找到附件
		set @_success = 1;
        return;
    end

	delete from 
		"waln_notifying"."attachments" 
	where 
		"Id" = @id; 

	-- 指示操作成功
	set @_success = 1;

	-- 记录操作日志
	set @_log_body = concat(N'删除了一个通知消息的附件文件：', @url, N'。');
	exec "waln_log"."log_op"
		@uploaderId, -- 当前用户的 Id
		8, -- 操作类型代码组合：1-查询、2-添加、4-更新、8-删除、16-其他
		'waln_notifying.attachments', -- 相关数据库表的名称列表
		'waln_notifying.p_outbox_deleteattachment', -- 存储过程名称
		@_success, -- 指示操作是否成功
		@_log_body, -- 详细的操作描述
		@_context, -- 当前环境变量参数
		@_log_id out; -- 日志消息的 Id
end
go

/*
 * -- 存储过程 - Sql Server:
 *   Create - 创建通知消息
 * 
 * -- 描述:
 *   创建一条新的通知消息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_service_create"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_service_create" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_service_create"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@receivers nvarchar(max), -- 接收用户 Id 的列表
	@urgency tinyint, -- 紧急程度 
	@group nvarchar(30), -- 分组 
	@title nvarchar(50), -- 通知标题 
	@summary nvarchar(200), -- 通知消息摘要 
	@body nvarchar(max), -- 通知正文内容 
	@bodyType tinyint, -- 正文类型代码 
	@funcUrl nvarchar(300), -- 目标功能路径 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@attachmentName nvarchar(100), -- 附件文件名称 
	@attachmentMime nvarchar(100), -- 附件 MIME 类型 
	@attachmentSize bigint, -- 附件文件的大小 
	@attachmentUrl nvarchar(300), -- 文件路径 
	@attachmentUploaderId uniqueidentifier, -- 上传人的 Id 
	@attachmentUploadTime datetime2, -- 上传时间 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;

	-- Id
	declare @attachmentId uniqueidentifier = null;
	-- 当前日期时间
	declare @now datetime2 = sysdatetime();
	-- 通知消息计数
	declare @notCount bigint = 0;

	-- 默认指示操作失败
	set @_success = 0;
	set @_message = N'';

	-- 验证参数 @senderId (发送用户的 Id)
	if @senderId is null
	begin
		set @_message = N'没有提供 发送用户的 Id。';
		return;
	end

	-- 验证参数 @receivers (接收用户 Id 的列表)
	if @receivers is null or @receivers = ''
	begin
		set @_message = N'没有提供 接收用户 Id 的列表。';
		return;
	end
	
    -- 验证参数 @urgency (紧急程度)
    if @urgency is null or @urgency not in (1, 2, 4) 
	begin
        set @_message = N'没有提供有效的紧急程度代码。';
        return;
    end

    -- 验证参数 @title (通知标题)
    if @title is null or @title = '' 
	begin
        set @_message = N'没有提供 通知标题。';
        return;
    end

    -- 验证参数 @body (通知正文内容)
    if @body is null or @body = '' 
	begin
        set @_message = N'没有提供 通知正文内容。';
        return;
    end

    -- 验证参数 @bodyType (正文类型代码)
    if @bodyType is null or @bodyType not in (1, 2) 
	begin
        set @bodyType = N'没有提供有效的 正文类型代码。';
        return;
    end

    -- 验证参数 @refDataType (引用数据的类型)
    if @refDataType is null or @refDataType = '' 
	begin
        set @_message = N'没有提供 引用数据的类型。';
        return;
    end

    -- 验证参数 @refDataKey (引用数据键值)
    if @refDataKey is null or @refDataKey = '' 
	begin
        set @_message = N'没有提供 引用数据键值。';
        return;
    end

    -- 验证参数 @attachmentName (附件文件名称)
    if @attachmentName is not null and @attachmentName <> '' 
	begin
		-- 验证参数 @attachmentMime (附件 MIME 类型)
		if @attachmentMime is null or @attachmentMime = '' 
		begin
			set @_message = N'没有提供 附件 MIME 类型。';
			return;
		end

		-- 验证参数 @attachmentSize (附件文件的大小)
		if @attachmentSize is null 
		begin
			set @_message = N'没有提供 附件文件的大小。';
			return;
		end

		-- 验证参数 @attachmentUrl (文件路径)
		if @attachmentUrl is null or @attachmentUrl = '' 
		begin
			set @_message = N'没有提供 文件路径。';
			return;
		end
        
		-- 验证参数 @attachmentUploaderId (上传人的 Id)
		if @attachmentUploaderId is null 
		begin
			set @attachmentUploaderId = @senderId;
		end

		-- 验证参数 @attachmentUploadTime (上传时间)
		if @attachmentUploadTime is null 
		begin
			set @attachmentUploadTime = @now;
		end
        
        set @attachmentId = newid();
    end

    -- 验证参数 @summary (通知消息摘要)
    if @summary is null or @summary = '' 
	begin
        set @summary = left(@body, 200);
    end

    insert into "waln_notifying"."notifications" 
    (
        "Id", -- Id 
        "SenderId", -- 发送用户的 Id 
        "ReceiverId", -- 接收用户的 Id 
        "ReceiveTime", -- 接收时间 
        "ReadTime", -- 阅读时间 
        "TopTime", -- 置顶时间 
        "Urgency", -- 紧急程度 
        "Group", -- 分组 
        "Title", -- 通知标题 
        "Summary", -- 通知消息摘要 
        "Body", -- 通知正文内容 
        "BodyType", -- 正文类型代码 
        "FuncUrl", -- 目标功能路径 
        "RefDataType", -- 引用数据的类型 
        "RefDataKey", -- 引用数据键值 
        "AttachmentId"  -- 附件 Id 
    )
    select 
        newid(), -- Id 
        @senderId, -- 发送用户的 Id 
        "Id", -- 接收用户的 Id 
        @now, -- 接收时间 
        null, -- 阅读时间 
        null, -- 置顶时间 
        @urgency, -- 紧急程度 
        @group, -- 分组 
        @title, -- 通知标题 
        @summary, -- 通知消息摘要 
        @body, -- 通知正文内容 
        @bodyType, -- 正文类型代码 
        @funcUrl, -- 目标功能路径 
        @refDataType, -- 引用数据的类型 
        @refDataKey, -- 引用数据键值 
        @attachmentId  -- 附件 Id 
    from
		"waln_authority"."users"
	where
		charindex("waln_authority"."uuid_to_b64"("Id") + ',', @receivers + ',') > 0;
        
	set @notCount = rowcount_big();
	
    if @notCount = 0 
	begin
        set @_message = N'没能创建任何通知消息，可能是目标接收人不是有效的用户。';
        return;
    end
    
    -- 创建附件
    if @attachmentId is not null 
	begin
		insert into "waln_notifying"."attachments" 
		(
			"Id", -- Id 
			"Name", -- 文件名称 
			"Mime", -- MIME 类型 
			"Size", -- 附件文件的大小 
			"Url", -- 文件路径 
			"UploaderId", -- 上传人的 Id 
			"UploadTime"  -- 上传时间 
		)
		values
		(
			@attachmentId, -- Id 
			@attachmentName, -- 文件名称 
			@attachmentMime, -- MIME 类型 
			@attachmentSize, -- 附件文件的大小 
			@attachmentUrl, -- 文件路径 
			@attachmentUploaderId, -- 上传人的 Id 
			@attachmentUploadTime  -- 上传时间 
		);
    end
    
    -- 指示操作成功
    set @_success = 1;
end
go

/*
 * -- 存储过程 - Sql Server:
 *   Update - 更新通知消息
 * 
 * -- 描述:
 *   按关联的数据更新一条通知消息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_service_update"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_service_update" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_service_update"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@urgency tinyint, -- 紧急程度 
	@group nvarchar(30), -- 分组 
	@title nvarchar(50), -- 通知标题 
	@summary nvarchar(200), -- 通知消息摘要 
	@body nvarchar(max), -- 通知正文内容 
	@bodyType tinyint, -- 正文类型代码 
	@funcUrl nvarchar(300), -- 目标功能路径 
	@attachmentName nvarchar(100), -- 附件文件名称 
	@attachmentMime nvarchar(100), -- 附件 MIME 类型 
	@attachmentSize bigint, -- 附件文件的大小 
	@attachmentUrl nvarchar(300), -- 文件路径 
	@attachmentUploaderId uniqueidentifier, -- 上传人的 Id 
	@attachmentUploadTime datetime2, -- 上传时间 
	@oldAttachmentUrl nvarchar(300) out, -- 原附件文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;
	
	-- 目标引用数据对应的第一条通知的主键
	declare @pk bigint = null;
    -- 当前日期时间
    declare @now datetime2 = sysdatetime();
    -- 原附件的 Id
    declare @oldAttachmentId uniqueidentifier = null;
    -- 新附件的 Id
    declare @newAttachmentId uniqueidentifier = null;
	-- 通知消息计数
	declare @notCount bigint = 0;

    -- 默认指示操作失败
    set @_success = 0;
    set @_message = N'';

    -- 初始化 out 参数 @oldAttachmentUrl (原附件文件路径)
    set @oldAttachmentUrl = null;

    -- 验证参数 @urgency (紧急程度)
    if @urgency is null or @urgency not in (1, 2, 4) 
	begin
        set @_message = N'没有提供有效的紧急程度代码。';
        return;
    end

    -- 验证参数 @title (通知标题)
    if @title is null or @title = '' 
	begin
        set @_message = N'没有提供 通知标题。';
        return;
    end

    -- 验证参数 @body (通知正文内容)
    if @body is null or @body = '' 
	begin
        set @_message = N'没有提供 通知正文内容。';
        return;
    end

    -- 验证参数 @bodyType (正文类型代码)
    if @bodyType is null or @bodyType not in (1, 2) 
	begin
        set @bodyType = N'没有提供有效的 正文类型代码。';
        return;
    end

    -- 验证参数 @refDataType (引用数据的类型)
    if @refDataType is null or @refDataType = '' 
	begin
        set @_message = N'没有提供 引用数据的类型。';
        return;
    end

    -- 验证参数 @refDataKey (引用数据键值)
    if @refDataKey is null or @refDataKey = '' 
	begin
        set @_message = N'没有提供 引用数据键值。';
        return;
    end
    
    -- 查询通知附件的 Id
    select top(1) @pk = "PK", @oldAttachmentId = "AttachmentId" 
    from "waln_notifying"."notifications"
    where "SenderId" = @senderId and "RefDataType" = @refDataType and "RefDataKey" = @refDataKey;

    if @pk is null 
	begin
        set @_message = N'没有找到目标通知消息。';
        return;
    end

    -- 验证参数 @attachmentName (附件文件名称)
    if @attachmentName is not null and @attachmentName <> '' 
	begin
		-- 验证参数 @attachmentMime (附件 MIME 类型)
		if @attachmentMime is null or @attachmentMime = '' 
		begin
			set @_message = N'没有提供 附件 MIME 类型。';
			return;
		end

		-- 验证参数 @attachmentSize (附件文件的大小)
		if @attachmentSize is null 
		begin
			set @_message = N'没有提供 附件文件的大小。';
			return;
		end

		-- 验证参数 @attachmentUrl (文件路径)
		if @attachmentUrl is null or @attachmentUrl = '' 
		begin
			set @_message = N'没有提供 文件路径。';
			return;
		end
        
		-- 验证参数 @attachmentUploaderId (上传人的 Id)
		if @attachmentUploaderId is null 
		begin
			set @attachmentUploaderId = @senderId;
		end

		-- 验证参数 @attachmentUploadTime (上传时间)
		if @attachmentUploadTime is null 
		begin
			set @attachmentUploadTime = @now;
		end
        
        set @newAttachmentId = newid();
    end

    -- 验证参数 @summary (通知消息摘要)
    if @summary is null or @summary = '' 
	begin
        set @summary = left(@body, 200);
    end
	
	-- 更新所有相关的通知消息
    update 
        "waln_notifying"."notifications" 
    set 
        "Urgency" = @urgency, 
        "Group" = @group, 
        "Title" = @title, 
        "Summary" = @summary, 
        "Body" = @body, 
        "BodyType" = @bodyType, 
        "FuncUrl" = @funcUrl,
        "AttachmentId" = case when @newAttachmentId is null then @oldAttachmentId else @newAttachmentId end
    where 
        "SenderId" = @senderId and "RefDataType" = @refDataType and "RefDataKey" = @refDataKey; 
        
    -- 查询更新的通知消息的数目
	set @notCount = rowcount_big();
    
    if @notCount = 0 
	begin
        set @_message = N'没有找到要更新的目标通知消息。';
        return;
    end

	-- 创建附件
    if @newAttachmentId is not null 
	begin
		insert into "waln_notifying"."attachments" 
		(
			"Id", -- Id 
			"Name", -- 文件名称 
			"Mime", -- MIME 类型 
			"Size", -- 附件文件的大小 
			"Url", -- 文件路径 
			"UploaderId", -- 上传人的 Id 
			"UploadTime"  -- 上传时间 
		)
		values
		(
			@newAttachmentId, -- Id 
			@attachmentName, -- 文件名称 
			@attachmentMime, -- MIME 类型 
			@attachmentSize, -- 附件文件的大小 
			@attachmentUrl, -- 文件路径 
			@attachmentUploaderId, -- 上传人的 Id 
			@attachmentUploadTime  -- 上传时间 
		);
        
        -- 删除原来的附件，返回 Update.oldAttachmentUrl
		if @oldAttachmentId is not null and not exists 
		(
			select 
				"PK" 
			from 
				"waln_notifying"."notifications" 
			where "AttachmentId" = @oldAttachmentId and 
				"SenderId" = @senderId and 
				"RefDataType" = @refDataType and 
				"RefDataKey" = @refDataKey
		) 
		begin
			-- 查询原来附件的路径
			select @oldAttachmentUrl = "Url" 
			from "waln_notifying"."attachments"
			where "Id" = @oldAttachmentId;
			
            -- 删除原来的附件记录
			delete from "waln_notifying"."attachments" where "Id" = @oldAttachmentId;
		end
	end
	else
	begin
		-- 附件没有变化
		set @newAttachmentId = @oldAttachmentId;
	end

    -- 指示操作成功
    set @_success = 1;
end
go

/*
 * -- 存储过程 - Sql Server:
 *   Delete - 删除通知消息
 * 
 * -- 描述:
 *   删除与指定的数据关联的通知消息。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_service_delete"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_service_delete" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_service_delete"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@attachmentUrl nvarchar(300) out, -- 附件文件路径 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 操作日志记录的 Id
	declare @_log_id bigint = null;
	declare @_log_body nvarchar(4000) = null;
	-- 主键
	declare @pk bigint = null;
    -- 附件的 Id
    declare @attachmentId uniqueidentifier = null;

    -- 默认指示操作失败
    set @_success = 0;
    set @_message = N'';
    set @attachmentUrl = null;

    -- 验证参数 @senderId (发送用户的 Id)
    if @senderId is null 
	begin
        set @_message = N'没有提供有效的 发送用户的 Id。';
        return;
    end

    -- 验证参数 @refDataType (引用数据的类型)
    if @refDataType is null or @refDataType = '' 
	begin
        set @_message = N'没有提供 引用数据的类型。';
        return;
    end

    -- 验证参数 @refDataKey (引用数据键值)
    if @refDataKey is null or @refDataKey = '' 
	begin
        set @_message = N'没有提供 引用数据键值。';
        return;
    end
	
	-- 查询附件的 Id
    select top(1)
        @pk = "PK", @attachmentId = "AttachmentId"
    from 
        "waln_notifying"."notifications"
    where 
        "SenderId" = @senderId and 
        "RefDataType" = @refDataType and 
        "RefDataKey" = @refDataKey;
        
	if @pk is null 
	begin
        set @_message = N'没有找到对应的通知记录。';
		return;
    end
    
	-- 如果没有其他通知消息使用该附件，则删除附件
    if @attachmentId is not null and not exists 
	(
		select 
			"PK" 
		from 
			"waln_notifying"."notifications" 
		where "AttachmentId" = @attachmentId and 
			"SenderId" = @senderId and 
			"RefDataType" = @refDataType and 
			"RefDataKey" = @refDataKey
	) 
	begin
		-- 返回附件文件的路径
		select @attachmentUrl = "Url"
        from "waln_notifying"."attachments"
        where "Id" = @attachmentId;
        
		-- 删除附件
        delete from "waln_notifying"."attachments" where "Id" = @attachmentId;
    end

	-- 删除相关的所有通知消息
    delete from 
        "waln_notifying"."notifications"
    where 
        "SenderId" = @senderId and 
        "RefDataType" = @refDataType and 
        "RefDataKey" = @refDataKey; 

    -- 指示操作成功
    set @_success = 1;
end
go

/*
 * -- 存储过程 - Sql Server:
 *   Details - 查询通知消息
 * 
 * -- 描述:
 *   查找与指定数据关联的通知消息及其附件。
 */

if not exists (select * from "sys"."objects" where "object_id" = object_id(N'"waln_notifying"."p_service_details"') and "type" in (N'P', N'PC'))
	exec('create procedure "waln_notifying"."p_service_details" as begin set nocount on; end');
go

alter procedure "waln_notifying"."p_service_details"
	@senderId uniqueidentifier, -- 发送用户的 Id 
	@refDataType nvarchar(64), -- 引用数据的类型 
	@refDataKey nvarchar(50), -- 引用数据键值 
	@_context nvarchar(4000), -- 当前环境变量参数
	@_success bit out, -- 指示操作是否成功 
	@_message nvarchar(4000) out  -- 操作中产生的消息 
as
begin
	-- 不自动向终端返回受影响行数的计数
	set nocount on;

	-- 主键
	declare @pk bigint = null;
    -- 附件的 Id
    declare @attachmentId uniqueidentifier = null;
    
    -- 默认指示操作失败
    set @_success = 0;
    set @_message = N'';

    -- 验证参数 @senderId (发送用户的 Id)
    if @senderId is null 
	begin
        set @_message = N'没有提供 发送用户的 Id。';
        return;
    end

    -- 验证参数 @refDataType (引用数据的类型)
    if @refDataType is null or @refDataType = '' 
	begin
        set @_message = N'没有提供 引用数据的类型。';
        return;
    end

    -- 验证参数 @refDataKey (引用数据键值)
    if @refDataKey is null or @refDataKey = '' 
	begin
        set @_message = N'没有提供 引用数据键值。';
        return;
    end
    
    select top(1)
        @pk = "PK", @attachmentId = "AttachmentId"
    from 
        "waln_notifying"."notifications"
    where 
        "SenderId" = @senderId and 
        "RefDataType" = @refDataType and 
        "RefDataKey" = @refDataKey;
        
	if @pk is null 
	begin
        set @_message = N'没有找到对应的通知记录。';
		return;
    end

    -- 返回 Details.notification
    select 
        v.* 
    from 
        "waln_notifying"."v_service_notification" as v 
    where 
        v."PK" = @pk; 

    -- 返回 Details.attachment
    if @attachmentId is not null 
	begin
		select 
			v.* 
		from 
			"waln_notifying"."v_service_attachment" as v 
		where 
			v."Id" = @attachmentId; 
	end

    -- 指示操作成功
    set @_success = 1;
end
go
